#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" WSGI applications for creating PDF output.

Reports require a title and a chunk of data sent by the client.

NOTE! Use DefaultTACKTemplate as your base class

Current expected format.  It can use these keys, but the only required
keys are title, name and sections.  

{"title": "The title of the report",
"name": "sales_by_quarter_01-07.pdf",
"sections":
 [
  {"title": "Subsection 1 Title",
   "table":
    {
     "headers": ["Col1", "Col2", "Col3"],
     "rows": [[1, 2, 3], [4, 5, 6]]
    }
  },
  {"title": "Subsection 2 Title",
   "table":
    {
     "headers": ["Col1", "Col2", "Col3"],
     "rows": [[1, 2, 3], [4, 5, 6]]
    }
  },
  {"title": "Subsection 3 Title",
   "text": "This is some text.\nAnd some more text."
  }
 ]
}

    >>> from urllib import quote_plus
    >>> from tack.lib import default_env, default_responder, run_app
    >>> from tack.lib.formreader import formreader
    >>> app = formreader(pdfreport())
    >>> json_data = file('tests/pdf.test.data').read()
    >>> env = default_env({'wsgi.input':StringIO('pdf=' + quote_plus(json_data) +
    ...                                           '&template=DefaultTACKTemplate'),
    ...                    'REQUEST_METHOD':'POST'})

    >>> d = run_app(app, env)
    >>> headers = d[0][1]
    >>> h = dict(headers)
    >>> h['Content-disposition']
    'inline; filename=sales_by_quarter_01-07.pdf'

    >>> h['Content-type']
    'application/pdf'

    >>> size = int(h['Content-length'])
    >>> 2600 <= size <= 2800
    True



"""
import reportlab.lib.pagesizes

from cStringIO import StringIO

from tack.lib.jsontools import json_loads

from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
                                TableStyle)
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
from reportlab.lib.units import inch

class DefaultTACKTemplate(SimpleDocTemplate):

    def __init__(self, filename, **kw):
        self.styles = getSampleStyleSheet()
        SimpleDocTemplate.__init__(self, filename, **kw)

        self.title = kw.get('title', '')

        self.PAGE_WIDTH = reportlab.lib.pagesizes.letter[0]
        self.PAGE_HEIGHT = reportlab.lib.pagesizes.letter[1]

    def afterInit(self):
        if hasattr(self, 'custom_style'):
            # s,d = style, definition
            for s,d in self.custom_style.items():
                for k,v in d.items():
                    setattr(self.styles[s], k, v)

    def getStyles(self):
        return self.styles

    def onFirstPage(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Bold',16)
        canvas.drawCentredString(self.PAGE_WIDTH/2.0, self.PAGE_HEIGHT-108,
                                 self.title)
        canvas.setFont('Times-Roman',9)
        canvas.drawString(inch, 0.75 * inch,
                          "First Page / %s" % self.title)
        canvas.restoreState()

    def onLaterPages(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Roman',9)
        canvas.drawString(inch, 0.75 * inch,
                          "Page %d %s" % (doc.page, self.title))
        canvas.restoreState()

class OCIETemplate(DefaultTACKTemplate):

    def __init__(self, filename, **kw):
        self.custom_style = {'Normal':
                        {'fontName':'Helvetica',}
                       }

        DefaultTACKTemplate.__init__(self, filename, **kw)

        self.title = kw.get('title', '')

    def onFirstPage(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Helvetica',16)
        canvas.drawCentredString(self.PAGE_WIDTH/2.0, self.PAGE_HEIGHT-108,
                                 self.title)
        canvas.setFont('Helvetica',9)
        canvas.drawString(inch, 0.75 * inch,
                          "First Page / %s" % self.title)
        canvas.restoreState()

    def onLaterPages(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Helvetica',9)
        canvas.drawString(inch, 0.75 * inch,
                          "Page %d %s" % (doc.page, self.title))
        canvas.restoreState()

class SalesReport(DefaultTACKTemplate):

    def __init__(self, filename, **kw):
        # Must be set before calling __init__ on base class
        self.custom_style = {'Normal':
                        {'fontName':'Helvetica',}
                       }

        DefaultTACKTemplate.__init__(self, filename, **kw)

        self.title = 'Sales Report: ' + kw.get('title', 'Default Title')

    def onFirstPage(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Bold',16)
        canvas.drawCentredString(self.PAGE_WIDTH/2.0, self.PAGE_HEIGHT-108,
                                 self.title)
        canvas.setFont('Times-Roman',9)
        canvas.drawString(inch, 0.75 * inch,
                          "Sales Report - First Page / %s" % self.title)
        canvas.restoreState()

    def onLaterPages(self, canvas, doc):
        canvas.saveState()
        canvas.setFont('Times-Roman',9)
        canvas.drawString(inch, 0.75 * inch,
                          "Sales Report - Page %d %s" % (doc.page, self.title))
        canvas.restoreState()

# Move the template name out to a parameter in the form
def pdfreport(template_name=None):
    """ Creates an application for rendering data with a given template.

    @param datasource
    @param template_name
    @return new WSGI application
    """

    def app(environ, start_response):

        doc_info = json_loads(environ['form']['pdf'])

        if 'template' in environ['form']:
            tn = environ['form']['template']
        elif template_name:
            tn = template_name
        else:
            tn = 'DefaultTACKTemplate'

        try :
            template = globals()[tn]
        except KeyError:
            raise KeyError('There is no report template named %s'
                           % tn)

        pdf = StringIO()
        doc = template(pdf, title=doc_info['title'])

        styles = doc.getStyles()
        stories = []

        for section in doc_info['sections']:
            if section.has_key('title'):
                stories.append(Paragraph(section['title'], styles['Heading1']))

            if section.has_key('table'):
                data = []
                data.append(section['table']['headers'])
                data.extend(section['table']['rows'])
                table_style = TableStyle([('FONTNAME',(0,0),(-1,-1),
                                           styles['Normal'].fontName),
                                          ('FONTSIZE',(0,0),(-1,-1),
                                           styles['Normal'].fontSize),
                                         ])
                stories.append(Table(data, style=table_style))

            if section.has_key('text'):
                for para in section['text'].split('\n'):
                    stories.append(Paragraph(para, styles['Normal']))

        Story = [Spacer(1,2*inch)]
        for story in stories:
            Story.append(story)
            Story.append(Spacer(1,0.1*inch))
        doc.build(Story)

        pdf.seek(0,2)

        start_response('200 OKAY', [('Content-type', 'application/pdf'),
                                    ('Content-length',str(pdf.tell())),
                                    ('Content-disposition',
                                     'inline; filename=%s' %
                                     str(doc_info.get('name','report.pdf')))])

        return pdf.getvalue()

    return app

